package io.github.houhanzhi.hhregistry.cluster;

import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class Election {
    
    public void electLeader(List<Server> servers) {
        // 获取集群中存活的leader
        final List<Server> masters =servers.stream()
                .filter(Server::isStatus)
                .filter(Server::isLeader)
                .collect(Collectors.toList());

        if (masters.isEmpty()) {
            log.debug(" ===> [ELECT] elect for no leader: " + servers);
            elect(servers);
        } else if (masters.size() > 1) {
            log.debug(" ===> [ELECT] elect for more than one leader: " + servers);
            elect(servers);
        } else {
            log.debug(" ===>  no need election for leader: " + masters.get(0));
        }
    }

    private void elect(List<Server> servers) {
        // 1、各个节点自己选，算法保证大家选的是同一个（此处选用该方法）
        // 2、外部有一个分布式锁，谁拿到锁，谁是主
        // 3、分布式一致性算法，比如paxos,raft...

        // 候选者
        Server candidate = null;

        for (Server server : servers) {
            // 先将所有的节点都设置为非leader，保证选举的leader唯一
            server.setLeader(false);
            if (server.isStatus()) {
                if (candidate == null) {
                    candidate = server;
                } else {
                    if (candidate.hashCode() > server.hashCode()) {
                        candidate = server;
                    }
                }
            }
        }

        if (candidate != null) {
            candidate.setLeader(true);
            log.debug(" ===> elect for leader: " + candidate);
        } else {
            log.debug(" ===> elect failed for no leaders: " + servers);
        }

    } 
}
